package cn.zhentao.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * AI聊天服务
 * 直接调用通义千问API
 *
 * @author zhentao
 */
@Service
@Slf4j
public class AiChatService {

    private final RestTemplate restTemplate = new RestTemplate();

    @Value("${ai.api-key:sk-8a4bac4735da4f79b19383d2b2696eac}")
    private String apiKey;

    @Value("${ai.base-url:https://dashscope.aliyuncs.com/compatible-mode/v1}")
    private String baseUrl;

    @Value("${ai.model-name:qwen-vl-plus}")
    private String modelName;

    /**
     * 发送消息到AI并获取回复
     */
    public String chat(String message) {
        try {
            // 构建更详细的提示词，要求AI给出明确答案
            String enhancedMessage = """
                你是一个专业的学习助手，请用中文回答以下问题。

                要求：
                1. 如果是数学题，请给出详细的解题步骤和最终答案
                2. 如果是选择题，请明确指出正确选项（如A、B、C、D）
                3. 如果是填空题，请给出具体的答案
                4. 如果是解答题，请提供完整的解答过程
                5. 答案要准确、清晰、易懂

                问题：%s

                请按以下格式回答：
                【题目分析】：...
                【解题步骤】：...
                【最终答案】：...
                """.formatted(message);

            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", modelName);

            List<Map<String, String>> messages = new ArrayList<>();
            Map<String, String> userMessage = new HashMap<>();
            userMessage.put("role", "user");
            userMessage.put("content", enhancedMessage);
            messages.add(userMessage);

            requestBody.put("messages", messages);
            requestBody.put("temperature", 0.7);
            requestBody.put("max_tokens", 2000);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(apiKey);

            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);

            // 发送请求
            String url = baseUrl + "/chat/completions";
            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

            if (response.getStatusCode() == HttpStatus.OK) {
                JSONObject jsonResponse = JSON.parseObject(response.getBody());
                if (jsonResponse.containsKey("choices") && 
                    jsonResponse.getJSONArray("choices").size() > 0) {
                    
                    JSONObject choice = jsonResponse.getJSONArray("choices").getJSONObject(0);
                    JSONObject message1 = choice.getJSONObject("message");
                    return message1.getString("content");
                }
            }

            log.error("AI API调用失败: {}", response.getBody());
            return "抱歉，AI服务暂时不可用，请稍后再试。";

        } catch (Exception e) {
            log.error("调用AI服务异常", e);
            return "抱歉，AI服务出现异常，请稍后再试。";
        }
    }

    /**
     * 分析题目（专门用于搜题功能）
     */
    public String analyzeQuestion(String ocrText) {
        String prompt = String.format("""
            你是一个专业的学习助手，请仔细分析以下题目并给出详细解答。

            题目内容：%s

            请按以下格式详细回答：

            【题目类型】：（如选择题、填空题、解答题等）
            【学科领域】：（如数学、物理、化学等）
            【知识点】：（涉及的主要知识点）
            【难度等级】：（1-5级，5为最难）

            【题目分析】：
            （详细分析题目要求和解题思路）

            【解题步骤】：
            步骤1：...
            步骤2：...
            步骤3：...
            （根据需要添加更多步骤）

            【最终答案】：
            （给出明确的最终答案，如果是选择题请指明选项，如果是计算题请给出数值结果）

            【解题要点】：
            （总结解题的关键点和注意事项）

            要求：
            1. 答案必须准确、完整
            2. 解题步骤要详细清晰
            3. 如果是选择题，必须明确指出正确选项
            4. 如果是计算题，必须给出具体数值
            5. 用中文回答
            """, ocrText);

        return chat(prompt);
    }

    /**
     * 生成相似题目
     */
    public String generateSimilarQuestions(String originalQuestion, int count) {
        String prompt = String.format("""
            基于以下原题，生成%d道相似的题目：
            
            原题：%s
            
            要求：
            1. 保持相同的知识点和题型
            2. 难度相当
            3. 题目表述清晰
            4. 每道题都要有完整的解答
            
            请以JSON数组格式返回，每个题目包含：
            {
                "question": "题目内容",
                "answer": "答案",
                "explanation": "解题思路"
            }
            """, count, originalQuestion);

        return chat(prompt);
    }

    /**
     * 学科分类
     */
    public String classifySubject(String questionText) {
        String prompt = String.format("""
            请分析以下题目属于哪个学科，只返回学科名称（如：数学、物理、化学、语文、英语等）：

            题目：%s

            请只返回一个学科名称，不要其他解释。
            """, questionText);

        try {
            String result = chat(prompt);
            return result.trim();
        } catch (Exception e) {
            log.error("学科分类失败", e);
            return "未知";
        }
    }

    /**
     * 题型识别
     */
    public String identifyQuestionType(String questionText) {
        String prompt = String.format("""
            请识别以下题目的类型（如：选择题、填空题、计算题、证明题、应用题等）：

            题目：%s

            请只返回题型名称，不要其他解释。
            """, questionText);

        try {
            String result = chat(prompt);
            return result.trim();
        } catch (Exception e) {
            log.error("题型识别失败", e);
            return "未知";
        }
    }

    /**
     * 知识点提取
     */
    public String extractKnowledgePoints(String questionText) {
        String prompt = String.format("""
            请提取以下题目涉及的主要知识点，用逗号分隔：

            题目：%s

            请只返回知识点列表，用逗号分隔，不要其他解释。
            """, questionText);

        try {
            String result = chat(prompt);
            return result.trim();
        } catch (Exception e) {
            log.error("知识点提取失败", e);
            return "基础知识";
        }
    }

    /**
     * 难度评估
     */
    public Integer assessDifficulty(String questionText) {
        String prompt = String.format("""
            请评估以下题目的难度等级（1-5级，1最简单，5最难）：

            题目：%s

            请只返回数字1-5，不要其他解释。
            """, questionText);

        try {
            String result = chat(prompt);
            String cleanResult = result.trim().replaceAll("[^0-9]", "");
            int difficulty = Integer.parseInt(cleanResult);
            return Math.max(1, Math.min(5, difficulty)); // 确保在1-5范围内
        } catch (Exception e) {
            log.error("难度评估失败", e);
            return 3; // 默认中等难度
        }
    }

    /**
     * 生成解题步骤
     */
    public String generateSolutionSteps(String questionText) {
        String prompt = String.format("""
            请为以下题目提供详细的解题步骤：

            题目：%s

            要求：
            1. 步骤清晰，逻辑严密
            2. 每一步都要有说明
            3. 使用中文回答
            4. 格式清晰易读
            """, questionText);

        try {
            return chat(prompt);
        } catch (Exception e) {
            log.error("生成解题步骤失败", e);
            return "解题步骤生成失败，请稍后重试";
        }
    }

    /**
     * 生成最终答案
     */
    public String generateFinalAnswer(String questionText) {
        String prompt = String.format("""
            请为以下题目提供最终答案，要求简洁明确：

            题目：%s

            请只返回最终答案，不要解题过程。
            """, questionText);

        try {
            String result = chat(prompt);
            return result.trim();
        } catch (Exception e) {
            log.error("生成最终答案失败", e);
            return "答案生成失败";
        }
    }

    /**
     * 计算置信度
     */
    public BigDecimal calculateConfidence(String questionText, String answer) {
        try {
            // 基于题目复杂度和答案完整性计算置信度
            double confidence = 0.8; // 基础置信度

            // 根据题目长度调整
            if (questionText.length() > 50) {
                confidence += 0.1;
            }

            // 根据答案完整性调整
            if (answer != null && answer.length() > 10) {
                confidence += 0.1;
            }

            // 确保在0.1-1.0范围内
            confidence = Math.max(0.1, Math.min(1.0, confidence));

            return BigDecimal.valueOf(confidence);
        } catch (Exception e) {
            log.error("计算置信度失败", e);
            return BigDecimal.valueOf(0.7);
        }
    }

    /**
     * 带上下文的聊天
     */
    public String chatWithContext(String contextMessage) {
        try {
            return chat(contextMessage);
        } catch (Exception e) {
            log.error("带上下文聊天失败", e);
            return "抱歉，我暂时无法回答您的问题，请稍后重试。";
        }
    }
}
